using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Xml;

namespace Brunch
{
    public class SerializationHelper
    {

        #region SerializeObject
        /// <summary>
        /// Method to convert a custom Object to XML string
        /// </summary>
        /// <param name="pObject">Object that is to be serialized to XML</param>
        /// <returns>XML string</returns>
        public static string SerializeObject(object obj)
        {
            try
            {
                String strSerialized = null;
                MemoryStream memoryStream = new MemoryStream();

                Type t = obj.GetType();
                XmlSerializer xs = new XmlSerializer(t);

                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

                xs.Serialize(xmlTextWriter, obj);
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                strSerialized = UTF8ByteArrayToString(memoryStream.ToArray());
                return strSerialized;
            }
            catch
            {
                return null;
            }
        }
        #endregion        

        #region DeserializeObject
        /// <summary>
        /// Method to reconstruct an Object from XML string
        /// </summary>
        /// <param name="pXmlizedString"></param>
        /// <returns></returns>
        public static object DeserializeObject(Type type, string seralizedString)
        {
            XmlSerializer xs = new XmlSerializer(type);
            MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(seralizedString));
            XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

            try
            {
                return xs.Deserialize(memoryStream);
            }
            catch
            {
                return null;
            }
        }

        #endregion

        #region SerializeObjectToFile
        public static void SerializeObjectToFile(object obj, string filename)
        {
            try
            {
                Type t = obj.GetType();
                XmlSerializer xs = new XmlSerializer(t);

                TextWriter tw = new StreamWriter(new FileStream(filename, FileMode.Create), Encoding.UTF8);
                XmlTextWriter xtw = new XmlTextWriter(tw);
                xtw.Formatting = Formatting.Indented;
                xs.Serialize(xtw, obj);
				xtw.Flush();
				xtw.Close();
            }
            catch
            {
                return;
            }
        }
        #endregion

        #region DeserializeObjectFromFile
        /// <summary>
        /// Method to reconstruct an Object from XML file
        /// </summary>
        /// <param name="type">The type being deserialized</param>
        /// <param name="filename">The file containing the object</param>
        /// <returns>Returns the object</returns>
        public static object DeserializeObjectFromFile(Type type, string filename)
        {
            //object retval;
            if (!File.Exists(filename))
                throw new FileNotFoundException("File not found [" + filename + "]");
            XmlSerializer serializer = new XmlSerializer(type);
            TextReader tr = new StreamReader(filename, Encoding.UTF8);
            XmlTextReader xtr = new XmlTextReader(tr);

            try
            {
                //XmlTextReader xtr = new XmlTextReader(filename);
                return serializer.Deserialize(xtr);
            }
            catch(Exception ex)
            {
                if (ex is InvalidOperationException)
                {
                    if ( (ex.InnerException !=null) && (ex.InnerException is System.Xml.XmlException) )
                    {
                        throw ex.InnerException;
                    }
                }
                throw;
            }
            finally
            {
				xtr.Close();
                tr.Close();
            }
        }

        public static T DeserializeObjectFromFile<T>(string filename)
        {
            return (T)DeserializeObjectFromFile(typeof(T), filename);
        }

        #endregion

        #region String <-> ByteArray conversions
        /// <summary>
        /// To convert a Byte Array of Unicode values (UTF-8 encoded) to a complete String.
        /// </summary>
        /// <param name="characters">Unicode Byte Array to be converted to String</param>
        /// <returns>String converted from Unicode Byte Array</returns>
        private static String UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            String constructedString = encoding.GetString(characters);
            return (constructedString);
        }

        /// <summary>
        /// Converts the String to UTF8 Byte array and is used in De serialization
        /// </summary>
        /// <param name="pXmlString"></param>
        /// <returns></returns>
        private static Byte[] StringToUTF8ByteArray(String pXmlString)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] byteArray = encoding.GetBytes(pXmlString);
            return byteArray;
        }

        #endregion

    }
}
